#include <iostream>
#include <opencv2/opencv.hpp>
#include <io.h>  // 遍历文件夹文件
#include <opencv2/core/utils/logger.hpp>
#include <windows.h>

#include "utils.hpp"

typedef NetDetect *(*InitDetectFunc)(const char *engine_file, const float &conf_threshold); // 定义函数指针类型
typedef Detection_ *(*OutResultFunc)(NetDetect *ud, int &height, int &width, const uchar *img_data,
                                     size_t &result_size);

typedef void (*FreeResultFunc)(Detection_ *result, size_t &result_size);

int main(int argc, char *argv[]) {
    //LOG_LEVEL_ERROR - 只输出错误日志 / LOG_LEVEL_SILENT - 不在输出日志
    cv::utils::logging::setLogLevel(cv::utils::logging::LOG_LEVEL_ERROR);

    // 图像全路径单斜杠需要转义，或者需要R"()"这样
    // 检测路径
//    std::string images_path = R"(D:\my_program\project\L_dianchi-20230404\data\L_dianchi_1\all_data\crop\images)";
    std::string images_path = R"(D:\my_program\project\L_dianchi-20230404\data\L_dianchi_1\all_data\all)";
    // 模型路径
    const char *engine_file = R"(D:\my_program\bushu\all_bushu\yolov5_detect\yolov5_onnxruntime_cpp\weights\best_20230407.onnx)";

    // 检测类别
    const std::vector<std::string> class_names = {"ng"};
    float conf_threshold = 0.3f;

    // 存储文件信息的结构体
    struct _finddata_t file_info;
    std::string current_path = images_path + "/*.jpg";  // 查找特定后缀的文件，支持通配符
    // 第一次查找，查找成功返回longlong型的句柄，失败返回-1
    long long handle = _findfirst(current_path.c_str(), &file_info);

    HINSTANCE hDll = LoadLibrary(
//            R"(D:\my_program\bushu\all_bushu\yolov5_detect\yolov5_onnx\lib\yolov5_onnx2dll.dll)"); // 加载 DLL 文件
            R"(D:\my_program\bushu\all_bushu\yolov5_detect\yolov5_onnxruntime_cpp\lib\yolov5_onnx2dll_nm.dll)"); // 加载 DLL 文件
    if (!hDll) {
        std::cerr << "Failed to load DLL" << std::endl;
        return 1;
    }

    auto createDetect = (InitDetectFunc) GetProcAddress(hDll, "InitDetect"); // 初始化类
    auto createResult = (OutResultFunc) GetProcAddress(hDll, "OutResult"); // 检测
    auto createFree = (FreeResultFunc) GetProcAddress(hDll, "FreeResult"); // 删除堆区创建的数据

    // 调用构造函数，初始化模型
    auto *ud = createDetect(engine_file,conf_threshold);
    auto colors = SetColor(class_names.size());

    do {
//        // 单张图像路径
        std::string img_path = images_path + "/" + file_info.name;
        std::cout << img_path << std::endl;
//
        // Mat是创建一个数组
        // IMREAD_COLOR/1-默认彩色  IMREAD_GRAYSCALE/0-灰度显示
        // IMREAD_UNCHANGED/-1-四通道png
        cv::Mat img = cv::imread(img_path, 1);
        int height = img.size().height;
        int width = img.size().width;
        uchar *imgdata = Img2Data(img);

        size_t result_size;
        // 侦测
        auto result_array = createResult(ud, height, width, imgdata, result_size);

        auto result_box = Array2Box(result_array, result_size);
        std::cout<<result_size<<std::endl;

        DrawImg(img, result_box, class_names, colors);

//        double start = clock();
//        for (int i = 0; i < 100; i++) {
//            //侦测
//            auto result_array = createResult(ud, height, width, imgdata, result_size);
//        }
//        double end = clock();
//        // 计算毫秒ms
//        double t = (end - start) / CLOCKS_PER_SEC * 1000;
//        std::cout << "detect_time: " << t << std::endl;

        std::cout << "============================" << std::endl;
        cv::namedWindow("show_img", cv::WINDOW_NORMAL);
        cv::imshow("show_img", img);
        cv::waitKey(0);

        createFree(result_array, result_size);
        delete[] imgdata;

    } while (!_findnext(handle, &file_info));  // 查找下一个
    _findclose(handle);  // 关闭

    delete ud;

    cv::destroyAllWindows();  // 销毁窗口
    system("pause");
}